/**
    Copyright (c) 2010-2011 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#include "DXUT.h"
#include "MandelbrotCPU.h"
#include "DXHelper.h"
#include "DataBufferDX11.h"

MandelbrotCPU::MandelbrotCPU()
{
}

MandelbrotCPU::~MandelbrotCPU()
{
}

void MandelbrotCPU::Create()
{
}

void MandelbrotCPU::OnFrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext )
{
    DataBufferDX11* pDataBuffer = reinterpret_cast< DataBufferDX11* >( pUserContext );

    const unsigned int nWidth = static_cast< unsigned int >( pDataBuffer->GetWidth() );
    const unsigned int nHeight = static_cast< unsigned int >( pDataBuffer->GetHeight() );
    BufType* buffer = pDataBuffer->GetpData();

    UpdateConstantBuf( nWidth, nHeight );
    
    unsigned int nIteration=0;

    for( unsigned int y=0; y<nHeight; ++y )
    {
        float cIm = m_cb.fMaxIm - y*m_cb.fStepIm;
        for(unsigned int x=0; x<nWidth; ++x)
        {
            float cRe = m_cb.fMinRe + x*m_cb.fStepRe;

            float zRe = cRe;
            float zIm = cIm;
            
            BufType color = BufType( 0.0f, 0.0f, 0.0f, 1.0f );

            for( nIteration=0; nIteration<m_nMaxIterations; ++nIteration )
            {
                float zRe2 = zRe*zRe;
                float zIm2 = zIm*zIm;
                
                /// check whether absolute value of z has gotten bigger than 2
                if( zRe2 + zIm2 > 4 ) {
                    break;
                }

                // calculate next z(n)
                zIm = 2*zRe*zIm + cIm;
                zRe = zRe2 - zIm2 + cRe;
            }
            
            if( nIteration != m_nMaxIterations ) { 
                if( nIteration < m_nMaxIterations/2 ) {
                    color = D3DXVECTOR4( nIteration / (static_cast< float >( m_nMaxIterations )/2.0f ), 0.0f, 0.0f, 1.0f );
                }
                else {
                    float fLerp = ( m_nMaxIterations-nIteration ) / ( static_cast< float >( m_nMaxIterations )/2.0f );
                    color = D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f )*(1.0f-fLerp)+D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f )*( fLerp );
                }        
            }

            buffer[ y*nWidth+ x ] = color;
        }
    }

    pDataBuffer->UpdateBuffer( pd3dDevice, pd3dImmediateContext );
}

void MandelbrotCPU::Destroy()
{
}